{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5e6e5d16",
   "metadata": {},
   "source": [
    "# Integrating Custom Data\n",
    "\n",
    "By combining your custom data with the feed data (order book and trades), you can enhance your strategy while harnessing the full potential of hftbacktest."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47864a60",
   "metadata": {},
   "source": [
    "## Accessing Spot Price\n",
    "\n",
    "In this example, we'll combine the spot BTCUSDT mid-price with the USDM-Futures BTCUSDT feed data. This will enable you to estimate the fair value price, taking the underlying price into consideration.\n",
    "\n",
    "The spot data is used only in the local-side, and thus, should come with a local timestamp. Following this, in your backtesting logic, your task is to identify the most recent data that predates the current timestamp."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3bd2277d",
   "metadata": {},
   "source": [
    "The raw spot feed is processed to create spot data, which includes both a local timestamp and the spot mid price."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b5b2a572",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import gzip\n",
    "import json\n",
    "\n",
    "spot = np.full((100_000, 2), np.nan, np.float64)\n",
    "i = 0\n",
    "\n",
    "with gzip.open('spot/btcusdt_20240809.gz', 'r') as f:\n",
    "    while True:\n",
    "        line = f.readline()\n",
    "        if line is None or line == b'':\n",
    "            break\n",
    "\n",
    "        line = line.decode().strip()\n",
    "        local_timestamp = int(line[:19])\n",
    "\n",
    "        obj = json.loads(line[20:])\n",
    "        if obj['stream'] == 'btcusdt@bookTicker':\n",
    "            data = obj['data']\n",
    "            mid = (float(data['b']) + float(data['a'])) / 2.0\n",
    "            spot[i] = [local_timestamp, mid]\n",
    "            i += 1\n",
    "            \n",
    "spot = spot[:i]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09180f41",
   "metadata": {},
   "source": [
    "It displays the basis and spot mid price as it identifies the latest Point-in-Time data that falls before the current timestamp."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d9bab818",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "current_timestamp: 1723161602500000000 futures_mid: 61659.85 , spot_mid: 61688.0 , basis: -28.14\n",
      "current_timestamp: 1723161612500000000 futures_mid: 61713.95 , spot_mid: 61727.8 , basis: -13.85\n",
      "current_timestamp: 1723161622500000000 futures_mid: 61713.45 , spot_mid: 61728.94 , basis: -15.5\n",
      "current_timestamp: 1723161632500000000 futures_mid: 61666.05 , spot_mid: 61690.08 , basis: -24.02\n",
      "current_timestamp: 1723161642500000000 futures_mid: 61638.45 , spot_mid: 61661.5 , basis: -23.06\n",
      "current_timestamp: 1723161652500000000 futures_mid: 61632.05 , spot_mid: 61663.98 , basis: -31.93\n",
      "current_timestamp: 1723161662500000000 futures_mid: 61578.15 , spot_mid: 61600.0 , basis: -21.85\n",
      "current_timestamp: 1723161672500000000 futures_mid: 61524.25 , spot_mid: 61562.0 , basis: -37.74\n",
      "current_timestamp: 1723161682500000000 futures_mid: 61552.45 , spot_mid: 61570.0 , basis: -17.54\n",
      "current_timestamp: 1723161692500000000 futures_mid: 61593.05 , spot_mid: 61606.0 , basis: -12.96\n",
      "current_timestamp: 1723161702500000000 futures_mid: 61587.45 , spot_mid: 61608.0 , basis: -20.54\n",
      "current_timestamp: 1723161712500000000 futures_mid: 61561.15 , spot_mid: 61589.88 , basis: -28.73\n",
      "current_timestamp: 1723161722500000000 futures_mid: 61589.95 , spot_mid: 61614.08 , basis: -24.14\n",
      "current_timestamp: 1723161732500000000 futures_mid: 61608.95 , spot_mid: 61632.13 , basis: -23.18\n",
      "current_timestamp: 1723161742500000000 futures_mid: 61653.45 , spot_mid: 61681.74 , basis: -28.29\n",
      "current_timestamp: 1723161752500000000 futures_mid: 61673.45 , spot_mid: 61700.0 , basis: -26.54\n",
      "current_timestamp: 1723161762500000000 futures_mid: 61663.95 , spot_mid: 61683.84 , basis: -19.89\n",
      "current_timestamp: 1723161772500000000 futures_mid: 61640.85 , spot_mid: 61664.0 , basis: -23.15\n",
      "current_timestamp: 1723161782500000000 futures_mid: 61634.15 , spot_mid: 61654.0 , basis: -19.85\n",
      "current_timestamp: 1723161792500000000 futures_mid: 61618.05 , spot_mid: 61666.0 , basis: -47.94\n",
      "current_timestamp: 1723161802500000000 futures_mid: 61626.65 , spot_mid: 61648.34 , basis: -21.69\n",
      "current_timestamp: 1723161812500000000 futures_mid: 61586.25 , spot_mid: 61612.0 , basis: -25.74\n",
      "current_timestamp: 1723161822500000000 futures_mid: 61624.65 , spot_mid: 61649.98 , basis: -25.33\n",
      "current_timestamp: 1723161832500000000 futures_mid: 61611.55 , spot_mid: 61644.0 , basis: -32.46\n",
      "current_timestamp: 1723161842500000000 futures_mid: 61633.95 , spot_mid: 61658.4 , basis: -24.46\n",
      "current_timestamp: 1723161852500000000 futures_mid: 61635.95 , spot_mid: 61656.02 , basis: -20.07\n",
      "current_timestamp: 1723161862500000000 futures_mid: 61671.45 , spot_mid: 61689.92 , basis: -18.47\n",
      "current_timestamp: 1723161872500000000 futures_mid: 61651.55 , spot_mid: 61664.0 , basis: -12.46\n",
      "current_timestamp: 1723161882500000000 futures_mid: 61614.15 , spot_mid: 61640.0 , basis: -25.84\n",
      "current_timestamp: 1723161892500000000 futures_mid: 61605.95 , spot_mid: 61622.12 , basis: -16.18\n",
      "current_timestamp: 1723161902500000000 futures_mid: 61583.95 , spot_mid: 61607.98 , basis: -24.04\n"
     ]
    }
   ],
   "source": [
    "from numba import njit\n",
    "from hftbacktest import BacktestAsset, HashMapMarketDepthBacktest\n",
    "\n",
    "out_dtype = np.dtype([('timestamp', 'i8'), ('mid_price', 'f8'), ('spot_mid_price', 'f8')])\n",
    "\n",
    "@njit\n",
    "def print_basis(hbt, spot):\n",
    "    out = np.empty(1_000_000, out_dtype)\n",
    "\n",
    "    t = 0\n",
    "    spot_row = 0\n",
    "    \n",
    "    # Checks every 60-sec (in nanoseconds)\n",
    "    while hbt.elapse(1_000_000_000) == 0:\n",
    "        # Finds the latest spot mid value.\n",
    "        while spot_row < len(spot) and spot[spot_row, 0] <= hbt.current_timestamp:\n",
    "            spot_row += 1\n",
    "        spot_mid_price = spot[spot_row - 1, 1] if spot_row > 0 else np.nan\n",
    "\n",
    "        depth = hbt.depth(0)\n",
    "        \n",
    "        mid_price = (depth.best_bid + depth.best_ask) / 2.0\n",
    "        basis = mid_price - spot_mid_price\n",
    "\n",
    "        if t % 10 == 0:\n",
    "            print(\n",
    "                'current_timestamp:',\n",
    "                hbt.current_timestamp,\n",
    "                'futures_mid:',\n",
    "                round(mid_price, 2),\n",
    "                ', spot_mid:',\n",
    "                round(spot_mid_price, 2),\n",
    "                ', basis:',\n",
    "                round(basis, 2)\n",
    "            )\n",
    "\n",
    "        out[t].timestamp = hbt.current_timestamp\n",
    "        out[t].mid_price = mid_price\n",
    "        out[t].spot_mid_price = spot_mid_price\n",
    "        t += 1\n",
    "        \n",
    "    return out[:t]\n",
    "\n",
    "asset = (\n",
    "    BacktestAsset()\n",
    "        .data(['usdm/btcusdt_20240809.npz'])\n",
    "        .initial_snapshot('usdm/btcusdt_20240808_eod.npz')\n",
    "        .linear_asset(1.0) \n",
    "        .constant_latency(10_000_000, 10_000_000)\n",
    "        .risk_adverse_queue_model() \n",
    "        .no_partial_fill_exchange()\n",
    "        .trading_value_fee_model(0.0002, 0.0007)\n",
    "        .tick_size(0.1)\n",
    "        .lot_size(0.001)\n",
    ")\n",
    "\n",
    "hbt = HashMapMarketDepthBacktest([asset])\n",
    "\n",
    "out = print_basis(hbt, spot)\n",
    "\n",
    "_ = hbt.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "0f18afc8-fd2d-4185-9094-dd7a1027ebf8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  var force = true;\n",
       "  var py_version = '3.4.2'.replace('rc', '-rc.').replace('.dev', '-dev.');\n",
       "  var reloading = false;\n",
       "  var Bokeh = root.Bokeh;\n",
       "\n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) {\n",
       "        if (callback != null)\n",
       "          callback();\n",
       "      });\n",
       "    } finally {\n",
       "      delete root._bokeh_onload_callbacks;\n",
       "    }\n",
       "    console.debug(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n",
       "    if (css_urls == null) css_urls = [];\n",
       "    if (js_urls == null) js_urls = [];\n",
       "    if (js_modules == null) js_modules = [];\n",
       "    if (js_exports == null) js_exports = {};\n",
       "\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    if (!reloading) {\n",
       "      console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    }\n",
       "\n",
       "    function on_load() {\n",
       "      root._bokeh_is_loading--;\n",
       "      if (root._bokeh_is_loading === 0) {\n",
       "        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
       "        run_callbacks()\n",
       "      }\n",
       "    }\n",
       "    window._bokeh_on_load = on_load\n",
       "\n",
       "    function on_error() {\n",
       "      console.error(\"failed to load \" + url);\n",
       "    }\n",
       "\n",
       "    var skip = [];\n",
       "    if (window.requirejs) {\n",
       "      window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n",
       "      root._bokeh_is_loading = css_urls.length + 0;\n",
       "    } else {\n",
       "      root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n",
       "    }\n",
       "\n",
       "    var existing_stylesheets = []\n",
       "    var links = document.getElementsByTagName('link')\n",
       "    for (var i = 0; i < links.length; i++) {\n",
       "      var link = links[i]\n",
       "      if (link.href != null) {\n",
       "\texisting_stylesheets.push(link.href)\n",
       "      }\n",
       "    }\n",
       "    for (var i = 0; i < css_urls.length; i++) {\n",
       "      var url = css_urls[i];\n",
       "      if (existing_stylesheets.indexOf(url) !== -1) {\n",
       "\ton_load()\n",
       "\tcontinue;\n",
       "      }\n",
       "      const element = document.createElement(\"link\");\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error;\n",
       "      element.rel = \"stylesheet\";\n",
       "      element.type = \"text/css\";\n",
       "      element.href = url;\n",
       "      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
       "      document.body.appendChild(element);\n",
       "    }    var existing_scripts = []\n",
       "    var scripts = document.getElementsByTagName('script')\n",
       "    for (var i = 0; i < scripts.length; i++) {\n",
       "      var script = scripts[i]\n",
       "      if (script.src != null) {\n",
       "\texisting_scripts.push(script.src)\n",
       "      }\n",
       "    }\n",
       "    for (var i = 0; i < js_urls.length; i++) {\n",
       "      var url = js_urls[i];\n",
       "      if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n",
       "\tif (!window.requirejs) {\n",
       "\t  on_load();\n",
       "\t}\n",
       "\tcontinue;\n",
       "      }\n",
       "      var element = document.createElement('script');\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error;\n",
       "      element.async = false;\n",
       "      element.src = url;\n",
       "      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.head.appendChild(element);\n",
       "    }\n",
       "    for (var i = 0; i < js_modules.length; i++) {\n",
       "      var url = js_modules[i];\n",
       "      if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n",
       "\tif (!window.requirejs) {\n",
       "\t  on_load();\n",
       "\t}\n",
       "\tcontinue;\n",
       "      }\n",
       "      var element = document.createElement('script');\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error;\n",
       "      element.async = false;\n",
       "      element.src = url;\n",
       "      element.type = \"module\";\n",
       "      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.head.appendChild(element);\n",
       "    }\n",
       "    for (const name in js_exports) {\n",
       "      var url = js_exports[name];\n",
       "      if (skip.indexOf(url) >= 0 || root[name] != null) {\n",
       "\tif (!window.requirejs) {\n",
       "\t  on_load();\n",
       "\t}\n",
       "\tcontinue;\n",
       "      }\n",
       "      var element = document.createElement('script');\n",
       "      element.onerror = on_error;\n",
       "      element.async = false;\n",
       "      element.type = \"module\";\n",
       "      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      element.textContent = `\n",
       "      import ${name} from \"${url}\"\n",
       "      window.${name} = ${name}\n",
       "      window._bokeh_on_load()\n",
       "      `\n",
       "      document.head.appendChild(element);\n",
       "    }\n",
       "    if (!js_urls.length && !js_modules.length) {\n",
       "      on_load()\n",
       "    }\n",
       "  };\n",
       "\n",
       "  function inject_raw_css(css) {\n",
       "    const element = document.createElement(\"style\");\n",
       "    element.appendChild(document.createTextNode(css));\n",
       "    document.body.appendChild(element);\n",
       "  }\n",
       "\n",
       "  var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.4.2.min.js\", \"https://cdn.holoviz.org/panel/1.4.4/dist/panel.min.js\"];\n",
       "  var js_modules = [];\n",
       "  var js_exports = {};\n",
       "  var css_urls = [];\n",
       "  var inline_js = [    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "function(Bokeh) {} // ensure no trailing comma for IE\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    if ((root.Bokeh !== undefined) || (force === true)) {\n",
       "      for (var i = 0; i < inline_js.length; i++) {\n",
       "\ttry {\n",
       "          inline_js[i].call(root, root.Bokeh);\n",
       "\t} catch(e) {\n",
       "\t  if (!reloading) {\n",
       "\t    throw e;\n",
       "\t  }\n",
       "\t}\n",
       "      }\n",
       "      // Cache old bokeh versions\n",
       "      if (Bokeh != undefined && !reloading) {\n",
       "\tvar NewBokeh = root.Bokeh;\n",
       "\tif (Bokeh.versions === undefined) {\n",
       "\t  Bokeh.versions = new Map();\n",
       "\t}\n",
       "\tif (NewBokeh.version !== Bokeh.version) {\n",
       "\t  Bokeh.versions.set(NewBokeh.version, NewBokeh)\n",
       "\t}\n",
       "\troot.Bokeh = Bokeh;\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    }\n",
       "    root._bokeh_is_initializing = false\n",
       "  }\n",
       "\n",
       "  function load_or_wait() {\n",
       "    // Implement a backoff loop that tries to ensure we do not load multiple\n",
       "    // versions of Bokeh and its dependencies at the same time.\n",
       "    // In recent versions we use the root._bokeh_is_initializing flag\n",
       "    // to determine whether there is an ongoing attempt to initialize\n",
       "    // bokeh, however for backward compatibility we also try to ensure\n",
       "    // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n",
       "    // before older versions are fully initialized.\n",
       "    if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n",
       "      root._bokeh_is_initializing = false;\n",
       "      root._bokeh_onload_callbacks = undefined;\n",
       "      console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n",
       "      load_or_wait();\n",
       "    } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n",
       "      setTimeout(load_or_wait, 100);\n",
       "    } else {\n",
       "      root._bokeh_is_initializing = true\n",
       "      root._bokeh_onload_callbacks = []\n",
       "      var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n",
       "      if (!reloading && !bokeh_loaded) {\n",
       "\troot.Bokeh = undefined;\n",
       "      }\n",
       "      load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n",
       "\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "\trun_inline_js();\n",
       "      });\n",
       "    }\n",
       "  }\n",
       "  // Give older versions of the autoload script a head-start to ensure\n",
       "  // they initialize before we start loading newer version.\n",
       "  setTimeout(load_or_wait, 100)\n",
       "}(window));"
      ],
      "application/vnd.holoviews_load.v0+json": "(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  var force = true;\n  var py_version = '3.4.2'.replace('rc', '-rc.').replace('.dev', '-dev.');\n  var reloading = false;\n  var Bokeh = root.Bokeh;\n\n  if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) {\n        if (callback != null)\n          callback();\n      });\n    } finally {\n      delete root._bokeh_onload_callbacks;\n    }\n    console.debug(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n    if (css_urls == null) css_urls = [];\n    if (js_urls == null) js_urls = [];\n    if (js_modules == null) js_modules = [];\n    if (js_exports == null) js_exports = {};\n\n    root._bokeh_onload_callbacks.push(callback);\n\n    if (root._bokeh_is_loading > 0) {\n      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n      run_callbacks();\n      return null;\n    }\n    if (!reloading) {\n      console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    }\n\n    function on_load() {\n      root._bokeh_is_loading--;\n      if (root._bokeh_is_loading === 0) {\n        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n        run_callbacks()\n      }\n    }\n    window._bokeh_on_load = on_load\n\n    function on_error() {\n      console.error(\"failed to load \" + url);\n    }\n\n    var skip = [];\n    if (window.requirejs) {\n      window.requirejs.config({'packages': {}, 'paths': {}, 'shim': {}});\n      root._bokeh_is_loading = css_urls.length + 0;\n    } else {\n      root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n    }\n\n    var existing_stylesheets = []\n    var links = document.getElementsByTagName('link')\n    for (var i = 0; i < links.length; i++) {\n      var link = links[i]\n      if (link.href != null) {\n\texisting_stylesheets.push(link.href)\n      }\n    }\n    for (var i = 0; i < css_urls.length; i++) {\n      var url = css_urls[i];\n      if (existing_stylesheets.indexOf(url) !== -1) {\n\ton_load()\n\tcontinue;\n      }\n      const element = document.createElement(\"link\");\n      element.onload = on_load;\n      element.onerror = on_error;\n      element.rel = \"stylesheet\";\n      element.type = \"text/css\";\n      element.href = url;\n      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n      document.body.appendChild(element);\n    }    var existing_scripts = []\n    var scripts = document.getElementsByTagName('script')\n    for (var i = 0; i < scripts.length; i++) {\n      var script = scripts[i]\n      if (script.src != null) {\n\texisting_scripts.push(script.src)\n      }\n    }\n    for (var i = 0; i < js_urls.length; i++) {\n      var url = js_urls[i];\n      if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t  on_load();\n\t}\n\tcontinue;\n      }\n      var element = document.createElement('script');\n      element.onload = on_load;\n      element.onerror = on_error;\n      element.async = false;\n      element.src = url;\n      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.head.appendChild(element);\n    }\n    for (var i = 0; i < js_modules.length; i++) {\n      var url = js_modules[i];\n      if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t  on_load();\n\t}\n\tcontinue;\n      }\n      var element = document.createElement('script');\n      element.onload = on_load;\n      element.onerror = on_error;\n      element.async = false;\n      element.src = url;\n      element.type = \"module\";\n      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.head.appendChild(element);\n    }\n    for (const name in js_exports) {\n      var url = js_exports[name];\n      if (skip.indexOf(url) >= 0 || root[name] != null) {\n\tif (!window.requirejs) {\n\t  on_load();\n\t}\n\tcontinue;\n      }\n      var element = document.createElement('script');\n      element.onerror = on_error;\n      element.async = false;\n      element.type = \"module\";\n      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      element.textContent = `\n      import ${name} from \"${url}\"\n      window.${name} = ${name}\n      window._bokeh_on_load()\n      `\n      document.head.appendChild(element);\n    }\n    if (!js_urls.length && !js_modules.length) {\n      on_load()\n    }\n  };\n\n  function inject_raw_css(css) {\n    const element = document.createElement(\"style\");\n    element.appendChild(document.createTextNode(css));\n    document.body.appendChild(element);\n  }\n\n  var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.4.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.4.2.min.js\", \"https://cdn.holoviz.org/panel/1.4.4/dist/panel.min.js\"];\n  var js_modules = [];\n  var js_exports = {};\n  var css_urls = [];\n  var inline_js = [    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n  ];\n\n  function run_inline_js() {\n    if ((root.Bokeh !== undefined) || (force === true)) {\n      for (var i = 0; i < inline_js.length; i++) {\n\ttry {\n          inline_js[i].call(root, root.Bokeh);\n\t} catch(e) {\n\t  if (!reloading) {\n\t    throw e;\n\t  }\n\t}\n      }\n      // Cache old bokeh versions\n      if (Bokeh != undefined && !reloading) {\n\tvar NewBokeh = root.Bokeh;\n\tif (Bokeh.versions === undefined) {\n\t  Bokeh.versions = new Map();\n\t}\n\tif (NewBokeh.version !== Bokeh.version) {\n\t  Bokeh.versions.set(NewBokeh.version, NewBokeh)\n\t}\n\troot.Bokeh = Bokeh;\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    }\n    root._bokeh_is_initializing = false\n  }\n\n  function load_or_wait() {\n    // Implement a backoff loop that tries to ensure we do not load multiple\n    // versions of Bokeh and its dependencies at the same time.\n    // In recent versions we use the root._bokeh_is_initializing flag\n    // to determine whether there is an ongoing attempt to initialize\n    // bokeh, however for backward compatibility we also try to ensure\n    // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n    // before older versions are fully initialized.\n    if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n      root._bokeh_is_initializing = false;\n      root._bokeh_onload_callbacks = undefined;\n      console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n      load_or_wait();\n    } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n      setTimeout(load_or_wait, 100);\n    } else {\n      root._bokeh_is_initializing = true\n      root._bokeh_onload_callbacks = []\n      var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n      if (!reloading && !bokeh_loaded) {\n\troot.Bokeh = undefined;\n      }\n      load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n\trun_inline_js();\n      });\n    }\n  }\n  // Give older versions of the autoload script a head-start to ensure\n  // they initialize before we start loading newer version.\n  setTimeout(load_or_wait, 100)\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n",
       "  window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n",
       "}\n",
       "\n",
       "\n",
       "    function JupyterCommManager() {\n",
       "    }\n",
       "\n",
       "    JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n",
       "      if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n",
       "        var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n",
       "        comm_manager.register_target(comm_id, function(comm) {\n",
       "          comm.on_msg(msg_handler);\n",
       "        });\n",
       "      } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n",
       "        window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n",
       "          comm.onMsg = msg_handler;\n",
       "        });\n",
       "      } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n",
       "        google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n",
       "          var messages = comm.messages[Symbol.asyncIterator]();\n",
       "          function processIteratorResult(result) {\n",
       "            var message = result.value;\n",
       "            console.log(message)\n",
       "            var content = {data: message.data, comm_id};\n",
       "            var buffers = []\n",
       "            for (var buffer of message.buffers || []) {\n",
       "              buffers.push(new DataView(buffer))\n",
       "            }\n",
       "            var metadata = message.metadata || {};\n",
       "            var msg = {content, buffers, metadata}\n",
       "            msg_handler(msg);\n",
       "            return messages.next().then(processIteratorResult);\n",
       "          }\n",
       "          return messages.next().then(processIteratorResult);\n",
       "        })\n",
       "      }\n",
       "    }\n",
       "\n",
       "    JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n",
       "      if (comm_id in window.PyViz.comms) {\n",
       "        return window.PyViz.comms[comm_id];\n",
       "      } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n",
       "        var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n",
       "        var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n",
       "        if (msg_handler) {\n",
       "          comm.on_msg(msg_handler);\n",
       "        }\n",
       "      } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n",
       "        var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n",
       "        comm.open();\n",
       "        if (msg_handler) {\n",
       "          comm.onMsg = msg_handler;\n",
       "        }\n",
       "      } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n",
       "        var comm_promise = google.colab.kernel.comms.open(comm_id)\n",
       "        comm_promise.then((comm) => {\n",
       "          window.PyViz.comms[comm_id] = comm;\n",
       "          if (msg_handler) {\n",
       "            var messages = comm.messages[Symbol.asyncIterator]();\n",
       "            function processIteratorResult(result) {\n",
       "              var message = result.value;\n",
       "              var content = {data: message.data};\n",
       "              var metadata = message.metadata || {comm_id};\n",
       "              var msg = {content, metadata}\n",
       "              msg_handler(msg);\n",
       "              return messages.next().then(processIteratorResult);\n",
       "            }\n",
       "            return messages.next().then(processIteratorResult);\n",
       "          }\n",
       "        }) \n",
       "        var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n",
       "          return comm_promise.then((comm) => {\n",
       "            comm.send(data, metadata, buffers, disposeOnDone);\n",
       "          });\n",
       "        };\n",
       "        var comm = {\n",
       "          send: sendClosure\n",
       "        };\n",
       "      }\n",
       "      window.PyViz.comms[comm_id] = comm;\n",
       "      return comm;\n",
       "    }\n",
       "    window.PyViz.comm_manager = new JupyterCommManager();\n",
       "    \n",
       "\n",
       "\n",
       "var JS_MIME_TYPE = 'application/javascript';\n",
       "var HTML_MIME_TYPE = 'text/html';\n",
       "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n",
       "var CLASS_NAME = 'output';\n",
       "\n",
       "/**\n",
       " * Render data to the DOM node\n",
       " */\n",
       "function render(props, node) {\n",
       "  var div = document.createElement(\"div\");\n",
       "  var script = document.createElement(\"script\");\n",
       "  node.appendChild(div);\n",
       "  node.appendChild(script);\n",
       "}\n",
       "\n",
       "/**\n",
       " * Handle when a new output is added\n",
       " */\n",
       "function handle_add_output(event, handle) {\n",
       "  var output_area = handle.output_area;\n",
       "  var output = handle.output;\n",
       "  if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
       "    return\n",
       "  }\n",
       "  var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "  var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "  if (id !== undefined) {\n",
       "    var nchildren = toinsert.length;\n",
       "    var html_node = toinsert[nchildren-1].children[0];\n",
       "    html_node.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "    var scripts = [];\n",
       "    var nodelist = html_node.querySelectorAll(\"script\");\n",
       "    for (var i in nodelist) {\n",
       "      if (nodelist.hasOwnProperty(i)) {\n",
       "        scripts.push(nodelist[i])\n",
       "      }\n",
       "    }\n",
       "\n",
       "    scripts.forEach( function (oldScript) {\n",
       "      var newScript = document.createElement(\"script\");\n",
       "      var attrs = [];\n",
       "      var nodemap = oldScript.attributes;\n",
       "      for (var j in nodemap) {\n",
       "        if (nodemap.hasOwnProperty(j)) {\n",
       "          attrs.push(nodemap[j])\n",
       "        }\n",
       "      }\n",
       "      attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n",
       "      newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n",
       "      oldScript.parentNode.replaceChild(newScript, oldScript);\n",
       "    });\n",
       "    if (JS_MIME_TYPE in output.data) {\n",
       "      toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n",
       "    }\n",
       "    output_area._hv_plot_id = id;\n",
       "    if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n",
       "      window.PyViz.plot_index[id] = Bokeh.index[id];\n",
       "    } else {\n",
       "      window.PyViz.plot_index[id] = null;\n",
       "    }\n",
       "  } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "    var bk_div = document.createElement(\"div\");\n",
       "    bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "    var script_attrs = bk_div.children[0].attributes;\n",
       "    for (var i = 0; i < script_attrs.length; i++) {\n",
       "      toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "    }\n",
       "    // store reference to server id on output_area\n",
       "    output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "  }\n",
       "}\n",
       "\n",
       "/**\n",
       " * Handle when an output is cleared or removed\n",
       " */\n",
       "function handle_clear_output(event, handle) {\n",
       "  var id = handle.cell.output_area._hv_plot_id;\n",
       "  var server_id = handle.cell.output_area._bokeh_server_id;\n",
       "  if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n",
       "  var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n",
       "  if (server_id !== null) {\n",
       "    comm.send({event_type: 'server_delete', 'id': server_id});\n",
       "    return;\n",
       "  } else if (comm !== null) {\n",
       "    comm.send({event_type: 'delete', 'id': id});\n",
       "  }\n",
       "  delete PyViz.plot_index[id];\n",
       "  if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n",
       "    var doc = window.Bokeh.index[id].model.document\n",
       "    doc.clear();\n",
       "    const i = window.Bokeh.documents.indexOf(doc);\n",
       "    if (i > -1) {\n",
       "      window.Bokeh.documents.splice(i, 1);\n",
       "    }\n",
       "  }\n",
       "}\n",
       "\n",
       "/**\n",
       " * Handle kernel restart event\n",
       " */\n",
       "function handle_kernel_cleanup(event, handle) {\n",
       "  delete PyViz.comms[\"hv-extension-comm\"];\n",
       "  window.PyViz.plot_index = {}\n",
       "}\n",
       "\n",
       "/**\n",
       " * Handle update_display_data messages\n",
       " */\n",
       "function handle_update_output(event, handle) {\n",
       "  handle_clear_output(event, {cell: {output_area: handle.output_area}})\n",
       "  handle_add_output(event, handle)\n",
       "}\n",
       "\n",
       "function register_renderer(events, OutputArea) {\n",
       "  function append_mime(data, metadata, element) {\n",
       "    // create a DOM node to render to\n",
       "    var toinsert = this.create_output_subarea(\n",
       "    metadata,\n",
       "    CLASS_NAME,\n",
       "    EXEC_MIME_TYPE\n",
       "    );\n",
       "    this.keyboard_manager.register_events(toinsert);\n",
       "    // Render to node\n",
       "    var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "    render(props, toinsert[0]);\n",
       "    element.append(toinsert);\n",
       "    return toinsert\n",
       "  }\n",
       "\n",
       "  events.on('output_added.OutputArea', handle_add_output);\n",
       "  events.on('output_updated.OutputArea', handle_update_output);\n",
       "  events.on('clear_output.CodeCell', handle_clear_output);\n",
       "  events.on('delete.Cell', handle_clear_output);\n",
       "  events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n",
       "\n",
       "  OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "    safe: true,\n",
       "    index: 0\n",
       "  });\n",
       "}\n",
       "\n",
       "if (window.Jupyter !== undefined) {\n",
       "  try {\n",
       "    var events = require('base/js/events');\n",
       "    var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  } catch(err) {\n",
       "  }\n",
       "}\n"
      ],
      "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n  window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n    function JupyterCommManager() {\n    }\n\n    JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n      if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n        var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n        comm_manager.register_target(comm_id, function(comm) {\n          comm.on_msg(msg_handler);\n        });\n      } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n        window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n          comm.onMsg = msg_handler;\n        });\n      } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n        google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n          var messages = comm.messages[Symbol.asyncIterator]();\n          function processIteratorResult(result) {\n            var message = result.value;\n            console.log(message)\n            var content = {data: message.data, comm_id};\n            var buffers = []\n            for (var buffer of message.buffers || []) {\n              buffers.push(new DataView(buffer))\n            }\n            var metadata = message.metadata || {};\n            var msg = {content, buffers, metadata}\n            msg_handler(msg);\n            return messages.next().then(processIteratorResult);\n          }\n          return messages.next().then(processIteratorResult);\n        })\n      }\n    }\n\n    JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n      if (comm_id in window.PyViz.comms) {\n        return window.PyViz.comms[comm_id];\n      } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n        var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n        var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n        if (msg_handler) {\n          comm.on_msg(msg_handler);\n        }\n      } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n        var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n        comm.open();\n        if (msg_handler) {\n          comm.onMsg = msg_handler;\n        }\n      } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n        var comm_promise = google.colab.kernel.comms.open(comm_id)\n        comm_promise.then((comm) => {\n          window.PyViz.comms[comm_id] = comm;\n          if (msg_handler) {\n            var messages = comm.messages[Symbol.asyncIterator]();\n            function processIteratorResult(result) {\n              var message = result.value;\n              var content = {data: message.data};\n              var metadata = message.metadata || {comm_id};\n              var msg = {content, metadata}\n              msg_handler(msg);\n              return messages.next().then(processIteratorResult);\n            }\n            return messages.next().then(processIteratorResult);\n          }\n        }) \n        var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n          return comm_promise.then((comm) => {\n            comm.send(data, metadata, buffers, disposeOnDone);\n          });\n        };\n        var comm = {\n          send: sendClosure\n        };\n      }\n      window.PyViz.comms[comm_id] = comm;\n      return comm;\n    }\n    window.PyViz.comm_manager = new JupyterCommManager();\n    \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n  var div = document.createElement(\"div\");\n  var script = document.createElement(\"script\");\n  node.appendChild(div);\n  node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n  var output_area = handle.output_area;\n  var output = handle.output;\n  if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n    return\n  }\n  var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n  var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n  if (id !== undefined) {\n    var nchildren = toinsert.length;\n    var html_node = toinsert[nchildren-1].children[0];\n    html_node.innerHTML = output.data[HTML_MIME_TYPE];\n    var scripts = [];\n    var nodelist = html_node.querySelectorAll(\"script\");\n    for (var i in nodelist) {\n      if (nodelist.hasOwnProperty(i)) {\n        scripts.push(nodelist[i])\n      }\n    }\n\n    scripts.forEach( function (oldScript) {\n      var newScript = document.createElement(\"script\");\n      var attrs = [];\n      var nodemap = oldScript.attributes;\n      for (var j in nodemap) {\n        if (nodemap.hasOwnProperty(j)) {\n          attrs.push(nodemap[j])\n        }\n      }\n      attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n      newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n      oldScript.parentNode.replaceChild(newScript, oldScript);\n    });\n    if (JS_MIME_TYPE in output.data) {\n      toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n    }\n    output_area._hv_plot_id = id;\n    if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n      window.PyViz.plot_index[id] = Bokeh.index[id];\n    } else {\n      window.PyViz.plot_index[id] = null;\n    }\n  } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n    var bk_div = document.createElement(\"div\");\n    bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n    var script_attrs = bk_div.children[0].attributes;\n    for (var i = 0; i < script_attrs.length; i++) {\n      toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n    }\n    // store reference to server id on output_area\n    output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n  }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n  var id = handle.cell.output_area._hv_plot_id;\n  var server_id = handle.cell.output_area._bokeh_server_id;\n  if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n  var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n  if (server_id !== null) {\n    comm.send({event_type: 'server_delete', 'id': server_id});\n    return;\n  } else if (comm !== null) {\n    comm.send({event_type: 'delete', 'id': id});\n  }\n  delete PyViz.plot_index[id];\n  if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n    var doc = window.Bokeh.index[id].model.document\n    doc.clear();\n    const i = window.Bokeh.documents.indexOf(doc);\n    if (i > -1) {\n      window.Bokeh.documents.splice(i, 1);\n    }\n  }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n  delete PyViz.comms[\"hv-extension-comm\"];\n  window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n  handle_clear_output(event, {cell: {output_area: handle.output_area}})\n  handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n  function append_mime(data, metadata, element) {\n    // create a DOM node to render to\n    var toinsert = this.create_output_subarea(\n    metadata,\n    CLASS_NAME,\n    EXEC_MIME_TYPE\n    );\n    this.keyboard_manager.register_events(toinsert);\n    // Render to node\n    var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n    render(props, toinsert[0]);\n    element.append(toinsert);\n    return toinsert\n  }\n\n  events.on('output_added.OutputArea', handle_add_output);\n  events.on('output_updated.OutputArea', handle_update_output);\n  events.on('clear_output.CodeCell', handle_clear_output);\n  events.on('delete.Cell', handle_clear_output);\n  events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n  OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n    safe: true,\n    index: 0\n  });\n}\n\nif (window.Jupyter !== undefined) {\n  try {\n    var events = require('base/js/events');\n    var OutputArea = require('notebook/js/outputarea').OutputArea;\n    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n      register_renderer(events, OutputArea);\n    }\n  } catch(err) {\n  }\n}\n"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style>*[data-root-id],\n",
       "*[data-root-id] > * {\n",
       "  box-sizing: border-box;\n",
       "  font-family: var(--jp-ui-font-family);\n",
       "  font-size: var(--jp-ui-font-size1);\n",
       "  color: var(--vscode-editor-foreground, var(--jp-ui-font-color1));\n",
       "}\n",
       "\n",
       "/* Override VSCode background color */\n",
       ".cell-output-ipywidget-background:has(\n",
       "    > .cell-output-ipywidget-background > .lm-Widget > *[data-root-id]\n",
       "  ),\n",
       ".cell-output-ipywidget-background:has(> .lm-Widget > *[data-root-id]) {\n",
       "  background-color: transparent !important;\n",
       "}\n",
       "</style>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.holoviews_exec.v0+json": "",
      "text/html": [
       "<div id='p1002'>\n",
       "  <div id=\"fb1b23a0-9dbf-44a4-924c-ac63073f644b\" data-root-id=\"p1002\" style=\"display: contents;\"></div>\n",
       "</div>\n",
       "<script type=\"application/javascript\">(function(root) {\n",
       "  var docs_json = {\"d77234e8-97b6-482d-81e1-b28950f89a43\":{\"version\":\"3.4.2\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"panel.models.browser.BrowserInfo\",\"id\":\"p1002\"},{\"type\":\"object\",\"name\":\"panel.models.comm_manager.CommManager\",\"id\":\"p1003\",\"attributes\":{\"plot_id\":\"p1002\",\"comm_id\":\"681ba5bca94042d9bf2849c6b065fc41\",\"client_comm_id\":\"db6efe02d08b45739e00a3b05945f5a2\"}}],\"defs\":[{\"type\":\"model\",\"name\":\"ReactiveHTML1\"},{\"type\":\"model\",\"name\":\"FlexBox1\",\"properties\":[{\"name\":\"align_content\",\"kind\":\"Any\",\"default\":\"flex-start\"},{\"name\":\"align_items\",\"kind\":\"Any\",\"default\":\"flex-start\"},{\"name\":\"flex_direction\",\"kind\":\"Any\",\"default\":\"row\"},{\"name\":\"flex_wrap\",\"kind\":\"Any\",\"default\":\"wrap\"},{\"name\":\"gap\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"justify_content\",\"kind\":\"Any\",\"default\":\"flex-start\"}]},{\"type\":\"model\",\"name\":\"FloatPanel1\",\"properties\":[{\"name\":\"config\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"contained\",\"kind\":\"Any\",\"default\":true},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"right-top\"},{\"name\":\"offsetx\",\"kind\":\"Any\",\"default\":null},{\"name\":\"offsety\",\"kind\":\"Any\",\"default\":null},{\"name\":\"theme\",\"kind\":\"Any\",\"default\":\"primary\"},{\"name\":\"status\",\"kind\":\"Any\",\"default\":\"normalized\"}]},{\"type\":\"model\",\"name\":\"GridStack1\",\"properties\":[{\"name\":\"mode\",\"kind\":\"Any\",\"default\":\"warn\"},{\"name\":\"ncols\",\"kind\":\"Any\",\"default\":null},{\"name\":\"nrows\",\"kind\":\"Any\",\"default\":null},{\"name\":\"allow_resize\",\"kind\":\"Any\",\"default\":true},{\"name\":\"allow_drag\",\"kind\":\"Any\",\"default\":true},{\"name\":\"state\",\"kind\":\"Any\",\"default\":[]}]},{\"type\":\"model\",\"name\":\"drag1\",\"properties\":[{\"name\":\"slider_width\",\"kind\":\"Any\",\"default\":5},{\"name\":\"slider_color\",\"kind\":\"Any\",\"default\":\"black\"},{\"name\":\"value\",\"kind\":\"Any\",\"default\":50}]},{\"type\":\"model\",\"name\":\"click1\",\"properties\":[{\"name\":\"terminal_output\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"debug_name\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"clears\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"FastWrapper1\",\"properties\":[{\"name\":\"object\",\"kind\":\"Any\",\"default\":null},{\"name\":\"style\",\"kind\":\"Any\",\"default\":null}]},{\"type\":\"model\",\"name\":\"NotificationAreaBase1\",\"properties\":[{\"name\":\"js_events\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"bottom-right\"},{\"name\":\"_clear\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"NotificationArea1\",\"properties\":[{\"name\":\"js_events\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"notifications\",\"kind\":\"Any\",\"default\":[]},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"bottom-right\"},{\"name\":\"_clear\",\"kind\":\"Any\",\"default\":0},{\"name\":\"types\",\"kind\":\"Any\",\"default\":[{\"type\":\"map\",\"entries\":[[\"type\",\"warning\"],[\"background\",\"#ffc107\"],[\"icon\",{\"type\":\"map\",\"entries\":[[\"className\",\"fas fa-exclamation-triangle\"],[\"tagName\",\"i\"],[\"color\",\"white\"]]}]]},{\"type\":\"map\",\"entries\":[[\"type\",\"info\"],[\"background\",\"#007bff\"],[\"icon\",{\"type\":\"map\",\"entries\":[[\"className\",\"fas fa-info-circle\"],[\"tagName\",\"i\"],[\"color\",\"white\"]]}]]}]}]},{\"type\":\"model\",\"name\":\"Notification\",\"properties\":[{\"name\":\"background\",\"kind\":\"Any\",\"default\":null},{\"name\":\"duration\",\"kind\":\"Any\",\"default\":3000},{\"name\":\"icon\",\"kind\":\"Any\",\"default\":null},{\"name\":\"message\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"notification_type\",\"kind\":\"Any\",\"default\":null},{\"name\":\"_destroyed\",\"kind\":\"Any\",\"default\":false}]},{\"type\":\"model\",\"name\":\"TemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"BootstrapTemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"TemplateEditor1\",\"properties\":[{\"name\":\"layout\",\"kind\":\"Any\",\"default\":[]}]},{\"type\":\"model\",\"name\":\"MaterialTemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"copy_to_clipboard1\",\"properties\":[{\"name\":\"fill\",\"kind\":\"Any\",\"default\":\"none\"},{\"name\":\"value\",\"kind\":\"Any\",\"default\":null}]}]}};\n",
       "  var render_items = [{\"docid\":\"d77234e8-97b6-482d-81e1-b28950f89a43\",\"roots\":{\"p1002\":\"fb1b23a0-9dbf-44a4-924c-ac63073f644b\"},\"root_ids\":[\"p1002\"]}];\n",
       "  var docs = Object.values(docs_json)\n",
       "  if (!docs) {\n",
       "    return\n",
       "  }\n",
       "  const py_version = docs[0].version.replace('rc', '-rc.').replace('.dev', '-dev.')\n",
       "  async function embed_document(root) {\n",
       "    var Bokeh = get_bokeh(root)\n",
       "    await Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "    for (const render_item of render_items) {\n",
       "      for (const root_id of render_item.root_ids) {\n",
       "\tconst id_el = document.getElementById(root_id)\n",
       "\tif (id_el.children.length && id_el.children[0].hasAttribute('data-root-id')) {\n",
       "\t  const root_el = id_el.children[0]\n",
       "\t  root_el.id = root_el.id + '-rendered'\n",
       "\t  for (const child of root_el.children) {\n",
       "            // Ensure JupyterLab does not capture keyboard shortcuts\n",
       "            // see: https://jupyterlab.readthedocs.io/en/4.1.x/extension/notebook.html#keyboard-interaction-model\n",
       "\t    child.setAttribute('data-lm-suppress-shortcuts', 'true')\n",
       "\t  }\n",
       "\t}\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "  function get_bokeh(root) {\n",
       "    if (root.Bokeh === undefined) {\n",
       "      return null\n",
       "    } else if (root.Bokeh.version !== py_version) {\n",
       "      if (root.Bokeh.versions === undefined || !root.Bokeh.versions.has(py_version)) {\n",
       "\treturn null\n",
       "      }\n",
       "      return root.Bokeh.versions.get(py_version);\n",
       "    } else if (root.Bokeh.version === py_version) {\n",
       "      return root.Bokeh\n",
       "    }\n",
       "    return null\n",
       "  }\n",
       "  function is_loaded(root) {\n",
       "    var Bokeh = get_bokeh(root)\n",
       "    return (Bokeh != null && Bokeh.Panel !== undefined)\n",
       "  }\n",
       "  if (is_loaded(root)) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (is_loaded(root)) {\n",
       "        clearInterval(timer);\n",
       "        embed_document(root);\n",
       "      } else if (document.readyState == \"complete\") {\n",
       "        attempts++;\n",
       "        if (attempts > 200) {\n",
       "          clearInterval(timer);\n",
       "\t  var Bokeh = get_bokeh(root)\n",
       "\t  if (Bokeh == null || Bokeh.Panel == null) {\n",
       "            console.warn(\"Panel: ERROR: Unable to run Panel code because Bokeh or Panel library is missing\");\n",
       "\t  } else {\n",
       "\t    console.warn(\"Panel: WARNING: Attempting to render but not all required libraries could be resolved.\")\n",
       "\t    embed_document(root)\n",
       "\t  }\n",
       "        }\n",
       "      }\n",
       "    }, 25, root)\n",
       "  }\n",
       "})(window);</script>"
      ]
     },
     "metadata": {
      "application/vnd.holoviews_exec.v0+json": {
       "id": "p1002"
      }
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<div class=\"logo-block\">\n",
       "<img src='\n",
       "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\n",
       "roTBs2RqAAAAAElFTkSuQmCC'\n",
       "     style='height:25px; border-radius:12px; display: inline-block; float: left; vertical-align: middle'></img>\n",
       "\n",
       "\n",
       "  <img src=''\n",
       "       style='height:15px; border-radius:12px; display: inline-block; float: left'></img>\n",
       "  \n",
       "\n",
       "\n",
       "\n",
       "\n",
       "</div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {},
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.holoviews_exec.v0+json": "",
      "text/html": [
       "<div id='p1004'>\n",
       "  <div id=\"cbeed9ea-542f-4487-a7b8-eebcc7f80de4\" data-root-id=\"p1004\" style=\"display: contents;\"></div>\n",
       "</div>\n",
       "<script type=\"application/javascript\">(function(root) {\n",
       "  var docs_json = {\"de1092b3-74b7-4673-b727-5d4c95ade1ac\":{\"version\":\"3.4.2\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"Row\",\"id\":\"p1004\",\"attributes\":{\"name\":\"Row00972\",\"tags\":[\"embedded\"],\"stylesheets\":[\"\\n:host(.pn-loading):before, .pn-loading:before {\\n  background-color: #c3c3c3;\\n  mask-size: auto calc(min(50%, 400px));\\n  -webkit-mask-size: auto calc(min(50%, 400px));\\n}\",{\"type\":\"object\",\"name\":\"ImportedStyleSheet\",\"id\":\"p1007\",\"attributes\":{\"url\":\"https://cdn.holoviz.org/panel/1.4.4/dist/css/loading.css\"}},{\"type\":\"object\",\"name\":\"ImportedStyleSheet\",\"id\":\"p1094\",\"attributes\":{\"url\":\"https://cdn.holoviz.org/panel/1.4.4/dist/css/listpanel.css\"}},{\"type\":\"object\",\"name\":\"ImportedStyleSheet\",\"id\":\"p1005\",\"attributes\":{\"url\":\"https://cdn.holoviz.org/panel/1.4.4/dist/bundled/theme/default.css\"}},{\"type\":\"object\",\"name\":\"ImportedStyleSheet\",\"id\":\"p1006\",\"attributes\":{\"url\":\"https://cdn.holoviz.org/panel/1.4.4/dist/bundled/theme/native.css\"}}],\"min_width\":700,\"margin\":0,\"sizing_mode\":\"stretch_width\",\"align\":\"start\",\"children\":[{\"type\":\"object\",\"name\":\"Spacer\",\"id\":\"p1008\",\"attributes\":{\"name\":\"HSpacer00979\",\"stylesheets\":[\"\\n:host(.pn-loading):before, .pn-loading:before {\\n  background-color: #c3c3c3;\\n  mask-size: auto calc(min(50%, 400px));\\n  -webkit-mask-size: auto calc(min(50%, 400px));\\n}\",{\"id\":\"p1007\"},{\"id\":\"p1005\"},{\"id\":\"p1006\"}],\"margin\":0,\"sizing_mode\":\"stretch_width\",\"align\":\"start\"}},{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1019\",\"attributes\":{\"width\":700,\"height\":300,\"margin\":[5,10],\"sizing_mode\":\"fixed\",\"align\":\"start\",\"x_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1009\",\"attributes\":{\"tags\":[[[\"timestamp\",null]],[]],\"start\":1723161602500.0,\"end\":1723161903500.0,\"reset_start\":1723161602500.0,\"reset_end\":1723161903500.0}},\"y_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1010\",\"attributes\":{\"tags\":[[[\"value\",null]],{\"type\":\"map\",\"entries\":[[\"invert_yaxis\",false],[\"autorange\",false]]}],\"start\":61500.3505,\"end\":61763.144499999995,\"reset_start\":61500.3505,\"reset_end\":61763.144499999995}},\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1029\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1030\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1022\",\"attributes\":{\"text_color\":\"black\",\"text_font_size\":\"12pt\"}},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1071\",\"attributes\":{\"name\":\"mid_price\",\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1062\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1063\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1064\"},\"data\":{\"type\":\"map\",\"entries\":[[\"timestamp\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AECc9kYTeUIAwNr2RhN5QgBAGfdGE3lCAMBX90YTeUIAQJb3RhN5QgDA1PdGE3lCAEAT+EYTeUIAwFH4RhN5QgBAkPhGE3lCAMDO+EYTeUIAQA35RhN5QgDAS/lGE3lCAECK+UYTeUIAwMj5RhN5QgBAB/pGE3lCAMBF+kYTeUIAQIT6RhN5QgDAwvpGE3lCAEAB+0YTeUIAwD/7RhN5QgBAfvtGE3lCAMC8+0YTeUIAQPv7RhN5QgDAOfxGE3lCAEB4/EYTeUIAwLb8RhN5QgBA9fxGE3lCAMAz/UYTeUIAQHL9RhN5QgDAsP1GE3lCAEDv/UYTeUIAwC3+RhN5QgBAbP5GE3lCAMCq/kYTeUIAQOn+RhN5QgDAJ/9GE3lCAEBm/0YTeUIAwKT/RhN5QgBA4/9GE3lCAMAhAEcTeUIAQGAARxN5QgDAngBHE3lCAEDdAEcTeUIAwBsBRxN5QgBAWgFHE3lCAMCYAUcTeUIAQNcBRxN5QgDAFQJHE3lCAEBUAkcTeUIAwJICRxN5QgBA0QJHE3lCAMAPA0cTeUIAQE4DRxN5QgDAjANHE3lCAEDLA0cTeUIAwAkERxN5QgBASARHE3lCAMCGBEcTeUIAQMUERxN5QgDAAwVHE3lCAEBCBUcTeUIAwIAFRxN5QgBAvwVHE3lCAMD9BUcTeUIAQDwGRxN5QgDAegZHE3lCAEC5BkcTeUIAwPcGRxN5QgBANgdHE3lCAMB0B0cTeUIAQLMHRxN5QgDA8QdHE3lCAEAwCEcTeUIAwG4IRxN5QgBArQhHE3lCAMDrCEcTeUIAQCoJRxN5QgDAaAlHE3lCAECnCUcTeUIAwOUJRxN5QgBAJApHE3lCAMBiCkcTeUIAQKEKRxN5QgDA3wpHE3lCAEAeC0cTeUIAwFwLRxN5QgBAmwtHE3lCAMDZC0cTeUIAQBgMRxN5QgDAVgxHE3lCAECVDEcTeUIAwNMMRxN5QgBAEg1HE3lCAMBQDUcTeUIAQI8NRxN5QgDAzQ1HE3lCAEAMDkcTeUIAwEoORxN5QgBAiQ5HE3lCAMDHDkcTeUIAQAYPRxN5QgDARA9HE3lCAECDD0cTeUIAwMEPRxN5QgBAABBHE3lCAMA+EEcTeUIAQH0QRxN5QgDAuxBHE3lCAED6EEcTeUIAwDgRRxN5QgBAdxFHE3lCAMC1EUcTeUIAQPQR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\"},\"shape\":[302],\"dtype\":\"float64\",\"order\":\"little\"}],[\"value\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"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\"},\"shape\":[302],\"dtype\":\"float64\",\"order\":\"little\"}],[\"Variable\",[\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\",\"mid_price\"]]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1072\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1073\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1068\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"value\"},\"line_color\":\"#30a2da\",\"line_width\":2}},\"selection_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1076\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"value\"},\"line_color\":\"#30a2da\",\"line_width\":2}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1069\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"value\"},\"line_color\":\"#30a2da\",\"line_alpha\":0.1,\"line_width\":2}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1070\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"value\"},\"line_color\":\"#30a2da\",\"line_alpha\":0.2,\"line_width\":2}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1086\",\"attributes\":{\"name\":\"spot_mid_price\",\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1077\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1078\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1079\"},\"data\":{\"type\":\"map\",\"entries\":[[\"timestamp\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AECc9kYTeUIAwNr2RhN5QgBAGfdGE3lCAMBX90YTeUIAQJb3RhN5QgDA1PdGE3lCAEAT+EYTeUIAwFH4RhN5QgBAkPhGE3lCAMDO+EYTeUIAQA35RhN5QgDAS/lGE3lCAECK+UYTeUIAwMj5RhN5QgBAB/pGE3lCAMBF+kYTeUIAQIT6RhN5QgDAwvpGE3lCAEAB+0YTeUIAwD/7RhN5QgBAfvtGE3lCAMC8+0YTeUIAQPv7RhN5QgDAOfxGE3lCAEB4/EYTeUIAwLb8RhN5QgBA9fxGE3lCAMAz/UYTeUIAQHL9RhN5QgDAsP1GE3lCAEDv/UYTeUIAwC3+RhN5QgBAbP5GE3lCAMCq/kYTeUIAQOn+RhN5QgDAJ/9GE3lCAEBm/0YTeUIAwKT/RhN5QgBA4/9GE3lCAMAhAEcTeUIAQGAARxN5QgDAngBHE3lCAEDdAEcTeUIAwBsBRxN5QgBAWgFHE3lCAMCYAUcTeUIAQNcBRxN5QgDAFQJHE3lCAEBUAkcTeUIAwJICRxN5QgBA0QJHE3lCAMAPA0cTeUIAQE4DRxN5QgDAjANHE3lCAEDLA0cTeUIAwAkERxN5QgBASARHE3lCAMCGBEcTeUIAQMUERxN5QgDAAwVHE3lCAEBCBUcTeUIAwIAFRxN5QgBAvwVHE3lCAMD9BUcTeUIAQDwGRxN5QgDAegZHE3lCAEC5BkcTeUIAwPcGRxN5QgBANgdHE3lCAMB0B0cTeUIAQLMHRxN5QgDA8QdHE3lCAEAwCEcTeUIAwG4IRxN5QgBArQhHE3lCAMDrCEcTeUIAQCoJRxN5QgDAaAlHE3lCAECnCUcTeUIAwOUJRxN5QgBAJApHE3lCAMBiCkcTeUIAQKEKRxN5QgDA3wpHE3lCAEAeC0cTeUIAwFwLRxN5QgBAmwtHE3lCAMDZC0cTeUIAQBgMRxN5QgDAVgxHE3lCAECVDEcTeUIAwNMMRxN5QgBAEg1HE3lCAMBQDUcTeUIAQI8NRxN5QgDAzQ1HE3lCAEAMDkcTeUIAwEoORxN5QgBAiQ5HE3lCAMDHDkcTeUIAQAYPRxN5QgDARA9HE3lCAECDD0cTeUIAwMEPRxN5QgBAABBHE3lCAMA+EEcTeUIAQH0QRxN5QgDAuxBHE3lCAED6EEcTeUIAwDgRRxN5QgBAdxFHE3lCAMC1EUcTeUIAQPQR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\"},\"shape\":[302],\"dtype\":\"float64\",\"order\":\"little\"}],[\"value\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"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\"},\"shape\":[302],\"dtype\":\"float64\",\"order\":\"little\"}],[\"Variable\",[\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\",\"spot_mid_price\"]]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1087\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1088\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1083\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"value\"},\"line_color\":\"#fc4f30\",\"line_width\":2}},\"selection_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1090\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"value\"},\"line_color\":\"#fc4f30\",\"line_width\":2}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1084\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"value\"},\"line_color\":\"#fc4f30\",\"line_alpha\":0.1,\"line_width\":2}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1085\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"value\"},\"line_color\":\"#fc4f30\",\"line_alpha\":0.2,\"line_width\":2}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1028\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1014\",\"attributes\":{\"tags\":[\"hv_created\"],\"renderers\":\"auto\",\"zoom_together\":\"none\"}},{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"p1015\",\"attributes\":{\"tags\":[\"hv_created\"],\"renderers\":[{\"id\":\"p1071\"},{\"id\":\"p1086\"}],\"tooltips\":[[\"Variable\",\"@{Variable}\"],[\"timestamp\",\"@{timestamp}{%F %T}\"],[\"value\",\"@{value}\"]],\"formatters\":{\"type\":\"map\",\"entries\":[[\"@{timestamp}\",\"datetime\"]]}}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1053\"},{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1054\"},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1055\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1056\",\"attributes\":{\"syncable\":false,\"level\":\"overlay\",\"visible\":false,\"left\":{\"type\":\"number\",\"value\":\"nan\"},\"right\":{\"type\":\"number\",\"value\":\"nan\"},\"top\":{\"type\":\"number\",\"value\":\"nan\"},\"bottom\":{\"type\":\"number\",\"value\":\"nan\"},\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"bottom_units\":\"canvas\",\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5}}}},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1061\"}],\"active_drag\":{\"id\":\"p1054\"},\"active_scroll\":{\"id\":\"p1014\"}}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1048\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1049\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1050\"},\"axis_label\":\"\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1051\"}}}],\"right\":[{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"p1074\",\"attributes\":{\"location\":[0,0],\"title\":\"Variable\",\"click_policy\":\"mute\",\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"p1075\",\"attributes\":{\"label\":{\"type\":\"value\",\"value\":\"mid_price\"},\"renderers\":[{\"id\":\"p1071\"}]}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"p1089\",\"attributes\":{\"label\":{\"type\":\"value\",\"value\":\"spot_mid_price\"},\"renderers\":[{\"id\":\"p1086\"}]}}]}}],\"below\":[{\"type\":\"object\",\"name\":\"DatetimeAxis\",\"id\":\"p1031\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"DatetimeTicker\",\"id\":\"p1032\",\"attributes\":{\"num_minor_ticks\":5,\"tickers\":[{\"type\":\"object\",\"name\":\"AdaptiveTicker\",\"id\":\"p1033\",\"attributes\":{\"num_minor_ticks\":0,\"mantissas\":[1,2,5],\"max_interval\":500.0}},{\"type\":\"object\",\"name\":\"AdaptiveTicker\",\"id\":\"p1034\",\"attributes\":{\"num_minor_ticks\":0,\"base\":60,\"mantissas\":[1,2,5,10,15,20,30],\"min_interval\":1000.0,\"max_interval\":1800000.0}},{\"type\":\"object\",\"name\":\"AdaptiveTicker\",\"id\":\"p1035\",\"attributes\":{\"num_minor_ticks\":0,\"base\":24,\"mantissas\":[1,2,4,6,8,12],\"min_interval\":3600000.0,\"max_interval\":43200000.0}},{\"type\":\"object\",\"name\":\"DaysTicker\",\"id\":\"p1036\",\"attributes\":{\"days\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]}},{\"type\":\"object\",\"name\":\"DaysTicker\",\"id\":\"p1037\",\"attributes\":{\"days\":[1,4,7,10,13,16,19,22,25,28]}},{\"type\":\"object\",\"name\":\"DaysTicker\",\"id\":\"p1038\",\"attributes\":{\"days\":[1,8,15,22]}},{\"type\":\"object\",\"name\":\"DaysTicker\",\"id\":\"p1039\",\"attributes\":{\"days\":[1,15]}},{\"type\":\"object\",\"name\":\"MonthsTicker\",\"id\":\"p1040\",\"attributes\":{\"months\":[0,1,2,3,4,5,6,7,8,9,10,11]}},{\"type\":\"object\",\"name\":\"MonthsTicker\",\"id\":\"p1041\",\"attributes\":{\"months\":[0,2,4,6,8,10]}},{\"type\":\"object\",\"name\":\"MonthsTicker\",\"id\":\"p1042\",\"attributes\":{\"months\":[0,4,8]}},{\"type\":\"object\",\"name\":\"MonthsTicker\",\"id\":\"p1043\",\"attributes\":{\"months\":[0,6]}},{\"type\":\"object\",\"name\":\"YearsTicker\",\"id\":\"p1044\"}]}},\"formatter\":{\"type\":\"object\",\"name\":\"DatetimeTickFormatter\",\"id\":\"p1045\"},\"axis_label\":\"timestamp\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1046\"}}}],\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1047\",\"attributes\":{\"axis\":{\"id\":\"p1031\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1052\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"p1048\"},\"grid_line_color\":null}}],\"min_border_top\":10,\"min_border_bottom\":10,\"min_border_left\":10,\"min_border_right\":10,\"output_backend\":\"webgl\"}},{\"type\":\"object\",\"name\":\"Spacer\",\"id\":\"p1092\",\"attributes\":{\"name\":\"HSpacer00980\",\"stylesheets\":[\"\\n:host(.pn-loading):before, .pn-loading:before {\\n  background-color: #c3c3c3;\\n  mask-size: auto calc(min(50%, 400px));\\n  -webkit-mask-size: auto calc(min(50%, 400px));\\n}\",{\"id\":\"p1007\"},{\"id\":\"p1005\"},{\"id\":\"p1006\"}],\"margin\":0,\"sizing_mode\":\"stretch_width\",\"align\":\"start\"}}]}}],\"defs\":[{\"type\":\"model\",\"name\":\"ReactiveHTML1\"},{\"type\":\"model\",\"name\":\"FlexBox1\",\"properties\":[{\"name\":\"align_content\",\"kind\":\"Any\",\"default\":\"flex-start\"},{\"name\":\"align_items\",\"kind\":\"Any\",\"default\":\"flex-start\"},{\"name\":\"flex_direction\",\"kind\":\"Any\",\"default\":\"row\"},{\"name\":\"flex_wrap\",\"kind\":\"Any\",\"default\":\"wrap\"},{\"name\":\"gap\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"justify_content\",\"kind\":\"Any\",\"default\":\"flex-start\"}]},{\"type\":\"model\",\"name\":\"FloatPanel1\",\"properties\":[{\"name\":\"config\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"contained\",\"kind\":\"Any\",\"default\":true},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"right-top\"},{\"name\":\"offsetx\",\"kind\":\"Any\",\"default\":null},{\"name\":\"offsety\",\"kind\":\"Any\",\"default\":null},{\"name\":\"theme\",\"kind\":\"Any\",\"default\":\"primary\"},{\"name\":\"status\",\"kind\":\"Any\",\"default\":\"normalized\"}]},{\"type\":\"model\",\"name\":\"GridStack1\",\"properties\":[{\"name\":\"mode\",\"kind\":\"Any\",\"default\":\"warn\"},{\"name\":\"ncols\",\"kind\":\"Any\",\"default\":null},{\"name\":\"nrows\",\"kind\":\"Any\",\"default\":null},{\"name\":\"allow_resize\",\"kind\":\"Any\",\"default\":true},{\"name\":\"allow_drag\",\"kind\":\"Any\",\"default\":true},{\"name\":\"state\",\"kind\":\"Any\",\"default\":[]}]},{\"type\":\"model\",\"name\":\"drag1\",\"properties\":[{\"name\":\"slider_width\",\"kind\":\"Any\",\"default\":5},{\"name\":\"slider_color\",\"kind\":\"Any\",\"default\":\"black\"},{\"name\":\"value\",\"kind\":\"Any\",\"default\":50}]},{\"type\":\"model\",\"name\":\"click1\",\"properties\":[{\"name\":\"terminal_output\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"debug_name\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"clears\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"FastWrapper1\",\"properties\":[{\"name\":\"object\",\"kind\":\"Any\",\"default\":null},{\"name\":\"style\",\"kind\":\"Any\",\"default\":null}]},{\"type\":\"model\",\"name\":\"NotificationAreaBase1\",\"properties\":[{\"name\":\"js_events\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"bottom-right\"},{\"name\":\"_clear\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"NotificationArea1\",\"properties\":[{\"name\":\"js_events\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"notifications\",\"kind\":\"Any\",\"default\":[]},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"bottom-right\"},{\"name\":\"_clear\",\"kind\":\"Any\",\"default\":0},{\"name\":\"types\",\"kind\":\"Any\",\"default\":[{\"type\":\"map\",\"entries\":[[\"type\",\"warning\"],[\"background\",\"#ffc107\"],[\"icon\",{\"type\":\"map\",\"entries\":[[\"className\",\"fas fa-exclamation-triangle\"],[\"tagName\",\"i\"],[\"color\",\"white\"]]}]]},{\"type\":\"map\",\"entries\":[[\"type\",\"info\"],[\"background\",\"#007bff\"],[\"icon\",{\"type\":\"map\",\"entries\":[[\"className\",\"fas fa-info-circle\"],[\"tagName\",\"i\"],[\"color\",\"white\"]]}]]}]}]},{\"type\":\"model\",\"name\":\"Notification\",\"properties\":[{\"name\":\"background\",\"kind\":\"Any\",\"default\":null},{\"name\":\"duration\",\"kind\":\"Any\",\"default\":3000},{\"name\":\"icon\",\"kind\":\"Any\",\"default\":null},{\"name\":\"message\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"notification_type\",\"kind\":\"Any\",\"default\":null},{\"name\":\"_destroyed\",\"kind\":\"Any\",\"default\":false}]},{\"type\":\"model\",\"name\":\"TemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"BootstrapTemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"TemplateEditor1\",\"properties\":[{\"name\":\"layout\",\"kind\":\"Any\",\"default\":[]}]},{\"type\":\"model\",\"name\":\"MaterialTemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"copy_to_clipboard1\",\"properties\":[{\"name\":\"fill\",\"kind\":\"Any\",\"default\":\"none\"},{\"name\":\"value\",\"kind\":\"Any\",\"default\":null}]}]}};\n",
       "  var render_items = [{\"docid\":\"de1092b3-74b7-4673-b727-5d4c95ade1ac\",\"roots\":{\"p1004\":\"cbeed9ea-542f-4487-a7b8-eebcc7f80de4\"},\"root_ids\":[\"p1004\"]}];\n",
       "  var docs = Object.values(docs_json)\n",
       "  if (!docs) {\n",
       "    return\n",
       "  }\n",
       "  const py_version = docs[0].version.replace('rc', '-rc.').replace('.dev', '-dev.')\n",
       "  async function embed_document(root) {\n",
       "    var Bokeh = get_bokeh(root)\n",
       "    await Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "    for (const render_item of render_items) {\n",
       "      for (const root_id of render_item.root_ids) {\n",
       "\tconst id_el = document.getElementById(root_id)\n",
       "\tif (id_el.children.length && id_el.children[0].hasAttribute('data-root-id')) {\n",
       "\t  const root_el = id_el.children[0]\n",
       "\t  root_el.id = root_el.id + '-rendered'\n",
       "\t  for (const child of root_el.children) {\n",
       "            // Ensure JupyterLab does not capture keyboard shortcuts\n",
       "            // see: https://jupyterlab.readthedocs.io/en/4.1.x/extension/notebook.html#keyboard-interaction-model\n",
       "\t    child.setAttribute('data-lm-suppress-shortcuts', 'true')\n",
       "\t  }\n",
       "\t}\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "  function get_bokeh(root) {\n",
       "    if (root.Bokeh === undefined) {\n",
       "      return null\n",
       "    } else if (root.Bokeh.version !== py_version) {\n",
       "      if (root.Bokeh.versions === undefined || !root.Bokeh.versions.has(py_version)) {\n",
       "\treturn null\n",
       "      }\n",
       "      return root.Bokeh.versions.get(py_version);\n",
       "    } else if (root.Bokeh.version === py_version) {\n",
       "      return root.Bokeh\n",
       "    }\n",
       "    return null\n",
       "  }\n",
       "  function is_loaded(root) {\n",
       "    var Bokeh = get_bokeh(root)\n",
       "    return (Bokeh != null && Bokeh.Panel !== undefined)\n",
       "  }\n",
       "  if (is_loaded(root)) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (is_loaded(root)) {\n",
       "        clearInterval(timer);\n",
       "        embed_document(root);\n",
       "      } else if (document.readyState == \"complete\") {\n",
       "        attempts++;\n",
       "        if (attempts > 200) {\n",
       "          clearInterval(timer);\n",
       "\t  var Bokeh = get_bokeh(root)\n",
       "\t  if (Bokeh == null || Bokeh.Panel == null) {\n",
       "            console.warn(\"Panel: ERROR: Unable to run Panel code because Bokeh or Panel library is missing\");\n",
       "\t  } else {\n",
       "\t    console.warn(\"Panel: WARNING: Attempting to render but not all required libraries could be resolved.\")\n",
       "\t    embed_document(root)\n",
       "\t  }\n",
       "        }\n",
       "      }\n",
       "    }, 25, root)\n",
       "  }\n",
       "})(window);</script>"
      ],
      "text/plain": [
       ":NdOverlay   [Variable]\n",
       "   :Curve   [timestamp]   (value)"
      ]
     },
     "execution_count": 3,
     "metadata": {
      "application/vnd.holoviews_exec.v0+json": {
       "id": "p1004"
      }
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import polars as pl\n",
    "import holoviews as hv\n",
    "\n",
    "df = pl.DataFrame(out).with_columns(\n",
    "    pl.from_epoch('timestamp', time_unit='ns').alias('timestamp')\n",
    ")\n",
    "\n",
    "hv.extension('bokeh')\n",
    "\n",
    "df.plot(x='timestamp')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d91e0cd-d30a-475e-82ac-ae91516a351e",
   "metadata": {},
   "source": [
    "Although this is a short-period sample, you can observe that the basis is mean-reverting. There may be statistical arbitrage opportunities, particularly if you are eligible for rebates or zero fees."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "695f935e-8fbe-43b9-8694-dd50f7a6874b",
   "metadata": {},
   "outputs": [
    {
     "data": {},
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.holoviews_exec.v0+json": "",
      "text/html": [
       "<div id='p1100'>\n",
       "  <div id=\"f5769519-f125-4679-8878-5ccfbaf3a672\" data-root-id=\"p1100\" style=\"display: contents;\"></div>\n",
       "</div>\n",
       "<script type=\"application/javascript\">(function(root) {\n",
       "  var docs_json = {\"8a775075-807a-4b52-9289-9684c7d63fc8\":{\"version\":\"3.4.2\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"Row\",\"id\":\"p1100\",\"attributes\":{\"name\":\"Row01103\",\"tags\":[\"embedded\"],\"stylesheets\":[\"\\n:host(.pn-loading):before, .pn-loading:before {\\n  background-color: #c3c3c3;\\n  mask-size: auto calc(min(50%, 400px));\\n  -webkit-mask-size: auto calc(min(50%, 400px));\\n}\",{\"type\":\"object\",\"name\":\"ImportedStyleSheet\",\"id\":\"p1103\",\"attributes\":{\"url\":\"https://cdn.holoviz.org/panel/1.4.4/dist/css/loading.css\"}},{\"type\":\"object\",\"name\":\"ImportedStyleSheet\",\"id\":\"p1159\",\"attributes\":{\"url\":\"https://cdn.holoviz.org/panel/1.4.4/dist/css/listpanel.css\"}},{\"type\":\"object\",\"name\":\"ImportedStyleSheet\",\"id\":\"p1101\",\"attributes\":{\"url\":\"https://cdn.holoviz.org/panel/1.4.4/dist/bundled/theme/default.css\"}},{\"type\":\"object\",\"name\":\"ImportedStyleSheet\",\"id\":\"p1102\",\"attributes\":{\"url\":\"https://cdn.holoviz.org/panel/1.4.4/dist/bundled/theme/native.css\"}}],\"min_width\":700,\"margin\":0,\"sizing_mode\":\"stretch_width\",\"align\":\"start\",\"children\":[{\"type\":\"object\",\"name\":\"Spacer\",\"id\":\"p1104\",\"attributes\":{\"name\":\"HSpacer01110\",\"stylesheets\":[\"\\n:host(.pn-loading):before, .pn-loading:before {\\n  background-color: #c3c3c3;\\n  mask-size: auto calc(min(50%, 400px));\\n  -webkit-mask-size: auto calc(min(50%, 400px));\\n}\",{\"id\":\"p1103\"},{\"id\":\"p1101\"},{\"id\":\"p1102\"}],\"margin\":0,\"sizing_mode\":\"stretch_width\",\"align\":\"start\"}},{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1112\",\"attributes\":{\"width\":700,\"height\":300,\"margin\":[5,10],\"sizing_mode\":\"fixed\",\"align\":\"start\",\"x_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1105\",\"attributes\":{\"tags\":[[[\"timestamp\",null]],[]],\"end\":301.0,\"reset_start\":0.0,\"reset_end\":301.0}},\"y_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1106\",\"attributes\":{\"tags\":[[[\"basis bp\",null]],{\"type\":\"map\",\"entries\":[[\"invert_yaxis\",false],[\"autorange\",false]]}],\"start\":-8.734345547079434,\"end\":2.705810180788002,\"reset_start\":-8.734345547079434,\"reset_end\":2.705810180788002}},\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1122\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1123\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1115\",\"attributes\":{\"text\":\"basis bp\",\"text_color\":\"black\",\"text_font_size\":\"12pt\"}},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1152\",\"attributes\":{\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1143\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1144\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1145\"},\"data\":{\"type\":\"map\",\"entries\":[[\"timestamp\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAEAAAACAAAAAwAAAAQAAAAFAAAABgAAAAcAAAAIAAAACQAAAAoAAAALAAAADAAAAA0AAAAOAAAADwAAABAAAAARAAAAEgAAABMAAAAUAAAAFQAAABYAAAAXAAAAGAAAABkAAAAaAAAAGwAAABwAAAAdAAAAHgAAAB8AAAAgAAAAIQAAACIAAAAjAAAAJAAAACUAAAAmAAAAJwAAACgAAAApAAAAKgAAACsAAAAsAAAALQAAAC4AAAAvAAAAMAAAADEAAAAyAAAAMwAAADQAAAA1AAAANgAAADcAAAA4AAAAOQAAADoAAAA7AAAAPAAAAD0AAAA+AAAAPwAAAEAAAABBAAAAQgAAAEMAAABEAAAARQAAAEYAAABHAAAASAAAAEkAAABKAAAASwAAAEwAAABNAAAATgAAAE8AAABQAAAAUQAAAFIAAABTAAAAVAAAAFUAAABWAAAAVwAAAFgAAABZAAAAWgAAAFsAAABcAAAAXQAAAF4AAABfAAAAYAAAAGEAAABiAAAAYwAAAGQAAABlAAAAZgAAAGcAAABoAAAAaQAAAGoAAABrAAAAbAAAAG0AAABuAAAAbwAAAHAAAABxAAAAcgAAAHMAAAB0AAAAdQAAAHYAAAB3AAAAeAAAAHkAAAB6AAAAewAAAHwAAAB9AAAAfgAAAH8AAACAAAAAgQAAAIIAAACDAAAAhAAAAIUAAACGAAAAhwAAAIgAAACJAAAAigAAAIsAAACMAAAAjQAAAI4AAACPAAAAkAAAAJEAAACSAAAAkwAAAJQAAACVAAAAlgAAAJcAAACYAAAAmQAAAJoAAACbAAAAnAAAAJ0AAACeAAAAnwAAAKAAAAChAAAAogAAAKMAAACkAAAApQAAAKYAAACnAAAAqAAAAKkAAACqAAAAqwAAAKwAAACtAAAArgAAAK8AAACwAAAAsQAAALIAAACzAAAAtAAAALUAAAC2AAAAtwAAALgAAAC5AAAAugAAALsAAAC8AAAAvQAAAL4AAAC/AAAAwAAAAMEAAADCAAAAwwAAAMQAAADFAAAAxgAAAMcAAADIAAAAyQAAAMoAAADLAAAAzAAAAM0AAADOAAAAzwAAANAAAADRAAAA0gAAANMAAADUAAAA1QAAANYAAADXAAAA2AAAANkAAADaAAAA2wAAANwAAADdAAAA3gAAAN8AAADgAAAA4QAAAOIAAADjAAAA5AAAAOUAAADmAAAA5wAAAOgAAADpAAAA6gAAAOsAAADsAAAA7QAAAO4AAADvAAAA8AAAAPEAAADyAAAA8wAAAPQAAAD1AAAA9gAAAPcAAAD4AAAA+QAAAPoAAAD7AAAA/AAAAP0AAAD+AAAA/wAAAAABAAABAQAAAgEAAAMBAAAEAQAABQEAAAYBAAAHAQAACAEAAAkBAAAKAQAACwEAAAwBAAANAQAADgEAAA8BAAAQAQAAEQEAABIBAAATAQAAFAEAABUBAAAWAQAAFwEAABgBAAAZAQAAGgEAABsBAAAcAQAAHQEAAB4BAAAfAQAAIAEAACEBAAAiAQAAIwEAACQBAAAlAQAAJgEAACcBAAAoAQAAKQEAACoBAAArAQAALAEAAC0BAAA=\"},\"shape\":[302],\"dtype\":\"int32\",\"order\":\"little\"}],[\"basis bp\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"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\"},\"shape\":[302],\"dtype\":\"float64\",\"order\":\"little\"}],[\"basis_bp\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"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\"},\"shape\":[302],\"dtype\":\"float64\",\"order\":\"little\"}]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1153\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1154\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1149\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"basis bp\"},\"line_color\":\"#30a2da\",\"line_width\":2}},\"selection_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1155\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"basis bp\"},\"line_color\":\"#30a2da\",\"line_width\":2}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1150\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"basis bp\"},\"line_color\":\"#30a2da\",\"line_alpha\":0.1,\"line_width\":2}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Line\",\"id\":\"p1151\",\"attributes\":{\"tags\":[\"apply_ranges\"],\"x\":{\"type\":\"field\",\"field\":\"timestamp\"},\"y\":{\"type\":\"field\",\"field\":\"basis bp\"},\"line_color\":\"#30a2da\",\"line_alpha\":0.2,\"line_width\":2}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1121\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1110\",\"attributes\":{\"tags\":[\"hv_created\"],\"renderers\":\"auto\",\"zoom_together\":\"none\"}},{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"p1111\",\"attributes\":{\"tags\":[\"hv_created\"],\"renderers\":[{\"id\":\"p1152\"}],\"tooltips\":[[\"timestamp\",\"@{timestamp}\"],[\"basis bp\",\"@{basis_bp}\"]]}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1134\"},{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1135\"},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1136\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1137\",\"attributes\":{\"syncable\":false,\"level\":\"overlay\",\"visible\":false,\"left\":{\"type\":\"number\",\"value\":\"nan\"},\"right\":{\"type\":\"number\",\"value\":\"nan\"},\"top\":{\"type\":\"number\",\"value\":\"nan\"},\"bottom\":{\"type\":\"number\",\"value\":\"nan\"},\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"bottom_units\":\"canvas\",\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5}}}},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1142\"}],\"active_drag\":{\"id\":\"p1135\"},\"active_scroll\":{\"id\":\"p1110\"}}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1129\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1130\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1131\"},\"axis_label\":\"\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1132\"}}}],\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1124\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1125\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1126\"},\"axis_label\":\"timestamp\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1127\"}}}],\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1128\",\"attributes\":{\"axis\":{\"id\":\"p1124\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1133\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"p1129\"},\"grid_line_color\":null}}],\"min_border_top\":10,\"min_border_bottom\":10,\"min_border_left\":10,\"min_border_right\":10,\"output_backend\":\"webgl\"}},{\"type\":\"object\",\"name\":\"Spacer\",\"id\":\"p1157\",\"attributes\":{\"name\":\"HSpacer01111\",\"stylesheets\":[\"\\n:host(.pn-loading):before, .pn-loading:before {\\n  background-color: #c3c3c3;\\n  mask-size: auto calc(min(50%, 400px));\\n  -webkit-mask-size: auto calc(min(50%, 400px));\\n}\",{\"id\":\"p1103\"},{\"id\":\"p1101\"},{\"id\":\"p1102\"}],\"margin\":0,\"sizing_mode\":\"stretch_width\",\"align\":\"start\"}}]}}],\"defs\":[{\"type\":\"model\",\"name\":\"ReactiveHTML1\"},{\"type\":\"model\",\"name\":\"FlexBox1\",\"properties\":[{\"name\":\"align_content\",\"kind\":\"Any\",\"default\":\"flex-start\"},{\"name\":\"align_items\",\"kind\":\"Any\",\"default\":\"flex-start\"},{\"name\":\"flex_direction\",\"kind\":\"Any\",\"default\":\"row\"},{\"name\":\"flex_wrap\",\"kind\":\"Any\",\"default\":\"wrap\"},{\"name\":\"gap\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"justify_content\",\"kind\":\"Any\",\"default\":\"flex-start\"}]},{\"type\":\"model\",\"name\":\"FloatPanel1\",\"properties\":[{\"name\":\"config\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"contained\",\"kind\":\"Any\",\"default\":true},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"right-top\"},{\"name\":\"offsetx\",\"kind\":\"Any\",\"default\":null},{\"name\":\"offsety\",\"kind\":\"Any\",\"default\":null},{\"name\":\"theme\",\"kind\":\"Any\",\"default\":\"primary\"},{\"name\":\"status\",\"kind\":\"Any\",\"default\":\"normalized\"}]},{\"type\":\"model\",\"name\":\"GridStack1\",\"properties\":[{\"name\":\"mode\",\"kind\":\"Any\",\"default\":\"warn\"},{\"name\":\"ncols\",\"kind\":\"Any\",\"default\":null},{\"name\":\"nrows\",\"kind\":\"Any\",\"default\":null},{\"name\":\"allow_resize\",\"kind\":\"Any\",\"default\":true},{\"name\":\"allow_drag\",\"kind\":\"Any\",\"default\":true},{\"name\":\"state\",\"kind\":\"Any\",\"default\":[]}]},{\"type\":\"model\",\"name\":\"drag1\",\"properties\":[{\"name\":\"slider_width\",\"kind\":\"Any\",\"default\":5},{\"name\":\"slider_color\",\"kind\":\"Any\",\"default\":\"black\"},{\"name\":\"value\",\"kind\":\"Any\",\"default\":50}]},{\"type\":\"model\",\"name\":\"click1\",\"properties\":[{\"name\":\"terminal_output\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"debug_name\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"clears\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"FastWrapper1\",\"properties\":[{\"name\":\"object\",\"kind\":\"Any\",\"default\":null},{\"name\":\"style\",\"kind\":\"Any\",\"default\":null}]},{\"type\":\"model\",\"name\":\"NotificationAreaBase1\",\"properties\":[{\"name\":\"js_events\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"bottom-right\"},{\"name\":\"_clear\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"NotificationArea1\",\"properties\":[{\"name\":\"js_events\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"notifications\",\"kind\":\"Any\",\"default\":[]},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"bottom-right\"},{\"name\":\"_clear\",\"kind\":\"Any\",\"default\":0},{\"name\":\"types\",\"kind\":\"Any\",\"default\":[{\"type\":\"map\",\"entries\":[[\"type\",\"warning\"],[\"background\",\"#ffc107\"],[\"icon\",{\"type\":\"map\",\"entries\":[[\"className\",\"fas fa-exclamation-triangle\"],[\"tagName\",\"i\"],[\"color\",\"white\"]]}]]},{\"type\":\"map\",\"entries\":[[\"type\",\"info\"],[\"background\",\"#007bff\"],[\"icon\",{\"type\":\"map\",\"entries\":[[\"className\",\"fas fa-info-circle\"],[\"tagName\",\"i\"],[\"color\",\"white\"]]}]]}]}]},{\"type\":\"model\",\"name\":\"Notification\",\"properties\":[{\"name\":\"background\",\"kind\":\"Any\",\"default\":null},{\"name\":\"duration\",\"kind\":\"Any\",\"default\":3000},{\"name\":\"icon\",\"kind\":\"Any\",\"default\":null},{\"name\":\"message\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"notification_type\",\"kind\":\"Any\",\"default\":null},{\"name\":\"_destroyed\",\"kind\":\"Any\",\"default\":false}]},{\"type\":\"model\",\"name\":\"TemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"BootstrapTemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"TemplateEditor1\",\"properties\":[{\"name\":\"layout\",\"kind\":\"Any\",\"default\":[]}]},{\"type\":\"model\",\"name\":\"MaterialTemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"copy_to_clipboard1\",\"properties\":[{\"name\":\"fill\",\"kind\":\"Any\",\"default\":\"none\"},{\"name\":\"value\",\"kind\":\"Any\",\"default\":null}]}]}};\n",
       "  var render_items = [{\"docid\":\"8a775075-807a-4b52-9289-9684c7d63fc8\",\"roots\":{\"p1100\":\"f5769519-f125-4679-8878-5ccfbaf3a672\"},\"root_ids\":[\"p1100\"]}];\n",
       "  var docs = Object.values(docs_json)\n",
       "  if (!docs) {\n",
       "    return\n",
       "  }\n",
       "  const py_version = docs[0].version.replace('rc', '-rc.').replace('.dev', '-dev.')\n",
       "  async function embed_document(root) {\n",
       "    var Bokeh = get_bokeh(root)\n",
       "    await Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "    for (const render_item of render_items) {\n",
       "      for (const root_id of render_item.root_ids) {\n",
       "\tconst id_el = document.getElementById(root_id)\n",
       "\tif (id_el.children.length && id_el.children[0].hasAttribute('data-root-id')) {\n",
       "\t  const root_el = id_el.children[0]\n",
       "\t  root_el.id = root_el.id + '-rendered'\n",
       "\t  for (const child of root_el.children) {\n",
       "            // Ensure JupyterLab does not capture keyboard shortcuts\n",
       "            // see: https://jupyterlab.readthedocs.io/en/4.1.x/extension/notebook.html#keyboard-interaction-model\n",
       "\t    child.setAttribute('data-lm-suppress-shortcuts', 'true')\n",
       "\t  }\n",
       "\t}\n",
       "      }\n",
       "    }\n",
       "  }\n",
       "  function get_bokeh(root) {\n",
       "    if (root.Bokeh === undefined) {\n",
       "      return null\n",
       "    } else if (root.Bokeh.version !== py_version) {\n",
       "      if (root.Bokeh.versions === undefined || !root.Bokeh.versions.has(py_version)) {\n",
       "\treturn null\n",
       "      }\n",
       "      return root.Bokeh.versions.get(py_version);\n",
       "    } else if (root.Bokeh.version === py_version) {\n",
       "      return root.Bokeh\n",
       "    }\n",
       "    return null\n",
       "  }\n",
       "  function is_loaded(root) {\n",
       "    var Bokeh = get_bokeh(root)\n",
       "    return (Bokeh != null && Bokeh.Panel !== undefined)\n",
       "  }\n",
       "  if (is_loaded(root)) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (is_loaded(root)) {\n",
       "        clearInterval(timer);\n",
       "        embed_document(root);\n",
       "      } else if (document.readyState == \"complete\") {\n",
       "        attempts++;\n",
       "        if (attempts > 200) {\n",
       "          clearInterval(timer);\n",
       "\t  var Bokeh = get_bokeh(root)\n",
       "\t  if (Bokeh == null || Bokeh.Panel == null) {\n",
       "            console.warn(\"Panel: ERROR: Unable to run Panel code because Bokeh or Panel library is missing\");\n",
       "\t  } else {\n",
       "\t    console.warn(\"Panel: WARNING: Attempting to render but not all required libraries could be resolved.\")\n",
       "\t    embed_document(root)\n",
       "\t  }\n",
       "        }\n",
       "      }\n",
       "    }, 25, root)\n",
       "  }\n",
       "})(window);</script>"
      ],
      "text/plain": [
       ":Curve   [timestamp]   (basis bp)"
      ]
     },
     "execution_count": 4,
     "metadata": {
      "application/vnd.holoviews_exec.v0+json": {
       "id": "p1100"
      }
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "((df['mid_price'] - df['spot_mid_price']) / df['mid_price'] * 10000).alias('basis bp').plot(x='timestamp')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
